package com.ruge.tool.bean;

import com.ruge.tool.json.JsonTool;
import com.ruge.tool.lambda.LambdaTool;
import com.ruge.tool.lambda.R;
import com.ruge.tool.str.StringTool;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * @author ruge.wu
 * @since 2021/12/24 16:26
 */
public class BeanTool {

    /**
     * 反射调用bean的get方法
     *
     * @param bean   bean class
     * @param column 字段名称
     * @param <T>    泛型
     * @return get后的属性
     */
    public static <T> Object get(Object bean, R<T> column) {
        return JsonTool.getObjToMap(bean).get(LambdaTool.convertToFieldName(column));
    }

    /**
     * 反射调用bean的set属性赋值 强制替换
     *
     * @param condition 判断条件
     * @param bean      bean class
     * @param column    待替换字段
     * @param value     替换后的值
     * @param <T>       class的泛型
     */
    public static <T> void set(Boolean condition, Object bean, R<T> column, String value) {
        set(condition, bean, column, value, true);
    }

    /**
     * 反射调用bean的set属性赋值 默认get有值不替换
     *
     * @param bean   bean class
     * @param column 待替换字段
     * @param value  替换后的值
     * @param <T>    class的泛型
     */
    public static <T> void set(Object bean, R<T> column, String value) {
        set(true, bean, column, value, false);
    }

    /**
     * 反射调用bean的set属性赋值
     *
     * @param bean      bean class
     * @param column    待替换字段
     * @param value     替换后的值
     * @param isReplace 是否强制替换
     * @param <T>       class的泛型
     */
    public static <T> void set(Object bean, R<T> column, String value, Boolean isReplace) {
        set(true, bean, column, value, isReplace);
    }


    /**
     * 反射调用bean的set属性赋值
     *
     * @param condition 判断条件
     * @param bean      bean class
     * @param column    待替换字段
     * @param value     替换后的值
     * @param isReplace 是否强制替换
     * @param <T>       class的泛型
     */
    public static <T> void set(Boolean condition, Object bean, R<T> column, String value, Boolean isReplace) {
        if (!condition) {
            return;
        }
        if (!isReplace && StringTool.isNotBlank(get(bean, column))) {
            return;
        }
        Class<?> cls = bean.getClass();
        // 取出bean里的所有方法
        Method[] methods = cls.getDeclaredMethods();
        // 取出bean里所有的字段
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            try {
                String fieldSetName = parSetName(field.getName());
                if (!checkSetMet(methods, fieldSetName)) {
                    continue;
                }
                Method fieldSetMet = cls.getMethod(fieldSetName, field.getType());
                String fieldKeyName = field.getName();
                String convertToFieldName = LambdaTool.convertToFieldName(column);
                if (fieldKeyName.equals(convertToFieldName)) {
                    if (StringTool.isNotBlank(value)) {
                        String fieldType = field.getType().getSimpleName();
                        if ("String".equals(fieldType)) {
                            fieldSetMet.invoke(bean, value);
                        } else if ("Date".equals(fieldType)) {
                            Date temp = parseDate(value);
                            fieldSetMet.invoke(bean, temp);
                        } else if ("Integer".equals(fieldType)
                                || "int".equals(fieldType)) {
                            Integer intval = Integer.parseInt(value);
                            fieldSetMet.invoke(bean, intval);
                        } else if ("Long".equalsIgnoreCase(fieldType)) {
                            Long temp = Long.parseLong(value);
                            fieldSetMet.invoke(bean, temp);
                        } else if ("Double".equalsIgnoreCase(fieldType)) {
                            Double temp = Double.parseDouble(value);
                            fieldSetMet.invoke(bean, temp);
                        } else if ("Boolean".equalsIgnoreCase(fieldType)) {
                            Boolean temp = Boolean.parseBoolean(value);
                            fieldSetMet.invoke(bean, temp);
                        } else {
                            System.out.println("not supper type" + fieldType);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 拼接在某属性的 set方法 字段名称
     *
     * @param fieldName 待拼接的字段
     * @return 拼接set后的方法名称
     */
    public static String parSetName(String fieldName) {
        if (null == fieldName || "".equals(fieldName)) {
            return null;
        }
        return "set".concat(StringTool.toUpperCaseFirstOne(fieldName));
    }

    /**
     * 格式化string为Date
     *
     * @param datestr 字符串时间
     * @return date
     */
    public static Date parseDate(String datestr) {
        if (null == datestr || "".equals(datestr)) {
            return null;
        }
        try {
            // 判断字符串中是否包含 ： 关键字 从而判断格式化方式
            String keyword = ":";
            String fmtstr;
            if (datestr.indexOf(keyword) > 0) {
                fmtstr = "yyyy-MM-dd HH:mm:ss";
            } else {
                fmtstr = "yyyy-MM-dd";
            }
            SimpleDateFormat sdf = new SimpleDateFormat(fmtstr, Locale.UK);
            return sdf.parse(datestr);
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 判断是否存在某属性的 set方法
     *
     * @param methods     方法集合
     * @param fieldSetMet 属性的set方法
     * @return 是否存在set方法
     */
    public static boolean checkSetMet(Method[] methods, String fieldSetMet) {
        for (Method met : methods) {
            if (fieldSetMet.equals(met.getName())) {
                return true;
            }
        }
        return false;
    }

}
